using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using Common.Utilities;
using PDFPARSERLib;
using Image=System.Drawing.Image;

namespace PdfLib
{
    /// <summary>
    /// 
    /// </summary>
    public class PdfDocumentReader
    {
        //#region general
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="pageNum"></param>
        ///// <returns></returns>
        //public static SizeF GetPageSize(string pdfFilePath, int pageNum)
        //{
        //    SizeF size = new SizeF();
        //    PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
        //    if (pdfDoc.Open(pdfFilePath, string.Empty))
        //    {
        //        pdfDoc.PageNo = pageNum;
        //        PDFPARSERLib.Page pdfPage = pdfDoc.Page;
        //        object[] dimensions = (object[])pdfPage.CropBox;
        //        if (dimensions != null && dimensions.Length == 4)
        //        {
        //            float pageHeight = float.Parse(dimensions[3].ToString());
        //            float pageWidth = float.Parse(dimensions[2].ToString());
        //            size = new SizeF(pageWidth, pageHeight);
        //        }
        //        pdfDoc.Close();
        //    }
        //    pdfDoc = null;
        //    return size;
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="pageNum"></param>
        ///// <returns></returns>
        //public static string GetPageContent(string pdfFilePath, int pageNum)
        //{
        //    System.Text.StringBuilder buffer = new System.Text.StringBuilder();
        //    PDFPARSERLib.Document doc = new PDFPARSERLib.Document();
        //    PDFPARSERLib.Content content = new PDFPARSERLib.Content();
        //    PDFPARSERLib.Text text = null;
            

        //    try
        //    {
        //        if (doc.Open(pdfFilePath, ""))
        //        {
        //            Single y1;

        //            y1 = -1;
        //            doc.PageNo = pageNum;
        //            PDFPARSERLib.Page page = doc.Page;
        //            PDFPARSERLib.Document pageDoc = page.Document;
        //            content = pageDoc.Page.Content;
        //            if (content != null)
        //            {
        //                content.BreakWords = false;
        //                do
        //                {
        //                    if (content.GetNextText() == null)
        //                    {
        //                        break;
        //                    }
        //                    text = content.Text;
        //                    string nodeText = text.UnicodeString;
        //                    float y2 = (float)((object[])text.YPos)[0];

        //                    if (y1 == y2)
        //                    {
        //                        buffer.Append(nodeText);
        //                    }
        //                    else
        //                    {
        //                        buffer.Append(Environment.NewLine);
        //                        buffer.Append(nodeText);
        //                    }
        //                    y1 = y2;
        //                } while (true);
        //            }
        //        }
        //        else
        //        {
        //            throw new Exception("Unable to open pdf file");
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        throw new Exception("Unable to read pdf page: "+ex.ToString());
        //    }
        //    finally
        //    {
        //        doc.Close();
        //    }
        //    if (buffer.Length == 0)
        //    {
        //        throw new Exception("Implement image extraction capability");
        //    }

        //    return buffer.ToString();
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="pageNum"></param>
        ///// <returns></returns>
        //public static Image GetPdfPageAsImage(string pdfFilePath, int pageNum)
        //{
        //    List<Image> imgs = new List<Image>();
        //    PDFPARSERLib.Document pdfDoc = new Document();
        //    try
        //    {
        //        if (pdfDoc.Open(pdfFilePath, string.Empty))
        //        {
        //            pdfDoc.PageNo = pageNum;
        //            PDFPARSERLib.Content pdfContent = pdfDoc.Page.Content;
        //            if (pdfContent != null)
        //            {
        //                PDFPARSERLib.Image pdfImg;
        //                pdfImg = pdfContent.GetNextImage();
        //                int i = 0;

        //                while (pdfImg != null)
        //                {
        //                    i++;
        //                    string tiffFilePath = pdfFilePath + "_" + pageNum + "_" + i.ToString() + ".tif";
        //                    pdfImg.Store(tiffFilePath, TPDFCompression.eComprRaw);
        //                    Image img = Image.FromFile(tiffFilePath);
        //                    imgs.Add(img);
        //                    pdfImg = pdfContent.GetNextImage();
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        throw new Exception("Unable to extract image: " + ex.ToString());
        //    }
        //    finally
        //    {
        //        pdfDoc.Close();
        //    }

        //    if (imgs.Count == 1)
        //        return new Bitmap(imgs[0]);
        //    else
        //        return null;
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <returns></returns>
        //public static PdfDocumentProperties GetPdfFileProperties(string pdfFilePath)
        //{
        //    PDFPARSERLib.Document doc=new Document();
        //    if(doc.Open(pdfFilePath,string.Empty))
        //    {
        //        PdfDocumentProperties properties=new PdfDocumentProperties();
        //        properties.Keywords = doc.Keywords;
        //        properties.ModificationTime = doc.ModDate;
        //        properties.Author = doc.Author;
        //        properties.Title = doc.Title;
        //        properties.PageCount = doc.PageCount;
        //        properties.Producer = doc.Producer;
        //        properties.CreationTime = doc.CreationDate;
        //        properties.Subject = doc.Subject;
        //        doc.Close();
        //        return properties;
        //    }
        //    else
        //    {
        //        throw new Exception("Unable to open pdf file");
        //    }
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="pageNum"></param>
        ///// <returns></returns>
        //public static List<PdfTextToken> ReadPageTextTokens(string pdfFilePath, int pageNum)
        //{
        //    List<PdfTextToken> textTokens = new List<PdfTextToken>();
        //    SizeF pageSize = PdfDocumentReader.GetPageSize(pdfFilePath, pageNum);
        //    PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
        //    if (pdfDoc.Open(pdfFilePath, ""))
        //    {
        //        pdfDoc.PageNo = pageNum;
        //        PDFPARSERLib.Content pdfContent = pdfDoc.Page.Content;
        //        if (pdfContent != null)
        //        {
        //            PDFPARSERLib.Text pdfText = pdfContent.GetNextText();
        //            while (pdfText != null)
        //            {
        //                string nodeText = pdfText.UnicodeString;
        //                float size = pdfText.FontSize;
        //                float x = (float)((object[])pdfText.XPos)[0];
        //                float y = (float)((object[])pdfText.YPos)[0];
        //                y = pageSize.Height - y;
        //                PdfTextToken txtToken = new PdfTextToken();
        //                txtToken.Text = nodeText;
        //                txtToken.Position = new PointF(x, y);
        //                txtToken.FontSize = size;
        //                float width = pdfText.Width;
        //                txtToken.TextRect = new RectangleF(x, y, width, size);
        //                textTokens.Add(txtToken);

        //                pdfText = pdfContent.GetNextText();
        //            }
        //        }
        //        pdfDoc.Close();
        //    }
        //    return textTokens;
        //}
        //#endregion

        #region seek pattern
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pdfFilePath"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public static PdfPosition SeekPattern(string pdfFilePath, string pattern)
        {
            Single x = 0;
            Single y = 0;
            System.Text.StringBuilder buffer = new StringBuilder();
            PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
            if (pdfDoc.Open(pdfFilePath, ""))
            {
                PDFPARSERLib.Content content = new PDFPARSERLib.Content();
                PDFPARSERLib.Text text = null;
                int pageCount = pdfDoc.PageCount;
                bool foundPattern = false;
                for (int pageNum = 1; pageNum <= pageCount; pageNum++)
                {
                    pdfDoc.PageNo = pageNum;
                    PDFPARSERLib.Page page = pdfDoc.Page;
                    PDFPARSERLib.Document pageDoc = page.Document;
                    content = pageDoc.Page.Content;
                    if (content == null)
                        text = null;
                    else
                        text = content.GetNextText();
                    while (text != null)
                    {
                        string nodeText = text.UnicodeString;
                        buffer.Append(" " + nodeText);
                        bool matched = StringUtil.Match(buffer.ToString(), pattern, StringMatchType.ExactMatch);
                        if (matched)
                        {
                            foundPattern = true;
                            break;
                        }
                        if (buffer.Length > 4000)
                        {
                            string lastSec = buffer.ToString().Substring(3500);
                            buffer = new StringBuilder();
                            buffer.Append(lastSec);
                        }
                        text = content.GetNextText();
                    }
                    if (foundPattern)
                        break;
                }
                x = 0f;
                y = 0f;
                if (text != null)
                {
                    x = (Single)((object[])text.XPos)[0];
                    y = (Single)((object[])text.YPos)[0];

                }
                if (!foundPattern)
                    throw new Exception("Unable to find pattern in pdf file");
            }
            else
            {
                pdfDoc.Close();
                throw new Exception("Unable to open pdf file");
            }
            PdfPosition destination = new PdfPosition();
            destination.PageNumber = pdfDoc.PageNo;
            destination.X = x;
            destination.Y = y;
            pdfDoc.Close();
            SizeF pageSize = PdfPropertyReader.GetPageSize(pdfFilePath, destination.PageNumber);
            destination.Y = pageSize.Height - y;
            return destination;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pdfFilePath"></param>
        /// <param name="pattern"></param>
        /// <param name="fromPageNum"></param>
        /// <returns></returns>
        public static PdfPosition SeekPatternAfterPage(string pdfFilePath, string pattern, int fromPageNum)
        {
            Single x = 0;
            Single y = 0;
            System.Text.StringBuilder buffer = new StringBuilder();
            PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
            if (pdfDoc.Open(pdfFilePath, ""))
            {
                PDFPARSERLib.Content content = new PDFPARSERLib.Content();
                PDFPARSERLib.Text text = null;
                int pageCount = pdfDoc.PageCount;
                if(pageCount >pageCount)
                {
                    pdfDoc.Close();
                    throw new Exception("Unable to open file after page number "+fromPageNum);
                }
                bool foundPattern = false;
                for (int pageNum = fromPageNum; pageNum <= pageCount; pageNum++)
                {
                    pdfDoc.PageNo = pageNum;
                    PDFPARSERLib.Page page = pdfDoc.Page;
                    PDFPARSERLib.Document pageDoc = page.Document;
                    content = pageDoc.Page.Content;
                    if (content == null)
                        text = null;
                    else
                        text = content.GetNextText();
                    while (text != null)
                    {
                        string nodeText = text.UnicodeString;
                        buffer.Append(" " + nodeText);
                        bool matched = StringUtil.Match(buffer.ToString(), pattern, StringMatchType.ExactMatch);
                        if (matched)
                        {
                            foundPattern = true;
                            break;
                        }
                        if (buffer.Length > 4000)
                        {
                            string lastSec = buffer.ToString().Substring(3500);
                            buffer = new StringBuilder();
                            buffer.Append(lastSec);
                        }
                        text = content.GetNextText();
                    }
                    if (foundPattern)
                        break;
                }
                x = 0f;
                y = 0f;
                if (text != null)
                {
                    x = (Single)((object[])text.XPos)[0];
                    y = (Single)((object[])text.YPos)[0];

                }
                if (!foundPattern)
                    throw new Exception("Unable to find pattern in pdf file");
            }
            else
            {
                pdfDoc.Close();
                throw new Exception("Unable to open pdf file");
            }
            PdfPosition destination = new PdfPosition();
            destination.PageNumber = pdfDoc.PageNo;
            destination.X = x;
            destination.Y = y;
            pdfDoc.Close();
            SizeF pageSize = PdfPropertyReader.GetPageSize(pdfFilePath, destination.PageNumber);
            destination.Y = pageSize.Height - y;
            return destination;
        }
        #endregion

        //#region bookmarks
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <returns></returns>
        //public static List<PdfBookmark> GetAllBookmarks(string pdfFilePath)
        //{
        //    int pageCount = PdfPropertyReader.GetPageCount(pdfFilePath);
        //    Dictionary<int,SizeF> pageSizes=new Dictionary<int, SizeF>();
        //    for(int i=1;i<=pageCount;i++)
        //    {
        //        SizeF pageSize = PdfPropertyReader.GetPageSize(pdfFilePath, i);
        //        pageSizes.Add(i,pageSize);
        //    }

        //    List<PdfBookmark> bookmarks=new List<PdfBookmark>();
        //    PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
        //    if (pdfDoc.Open(pdfFilePath, ""))
        //    {
        //        string lastPath = string.Empty;
        //        int lastDepth = 0;
        //        OutlineItem outline = pdfDoc.GetFirstOutlineItem();
        //        PdfBookmark lastBookmark = null;
        //        while(outline !=null && pageSizes.ContainsKey(outline.Dest.PageNo))
        //        {
        //            SizeF pageSize = pageSizes[outline.Dest.PageNo];
        //            PdfBookmark bookmark=new PdfBookmark();
        //            bookmark.BookmarkID = -1;
        //            bookmark.FromPageNumber = outline.Dest.PageNo;
        //            bookmark.FromPosition=new PointF(outline.Dest.Left, pageSize.Height - outline.Dest.Top);
        //            bookmark.ToPageNumber = pageCount;
        //            bookmark.ToPosition = new PointF(pageSize.Width, pageSize.Height);
        //            bookmark.Title = outline.Title;
        //            int depth = pdfDoc.GetCurrentOutlineLevel();
        //            if (string.IsNullOrEmpty(lastPath))
        //            {
        //                bookmark.Path = PdfDocumentReader.ToNodeName(0);
        //            }
        //            else if(depth==lastDepth)
        //            {
        //                string parentPath = PdfDocumentReader.GetParentPath(lastPath);
        //                int currentIndex = PdfDocumentReader.GetLastSiblingIndex(lastPath) + 1;
        //                if(string.IsNullOrEmpty(parentPath))
        //                {
        //                    bookmark.Path = PdfDocumentReader.ToNodeName(currentIndex);
        //                }
        //                else
        //                {
        //                    bookmark.Path = parentPath + "." + PdfDocumentReader.ToNodeName(currentIndex);
        //                }
        //            }
        //            else if(depth >lastDepth)
        //            {
        //                int currentIndex = 0;
        //                bookmark.Path = lastPath + "." + PdfDocumentReader.ToNodeName(currentIndex);
        //            }
        //            else // (depth <lastDepth)
        //            {
        //                string parentPath = PdfDocumentReader.GetParentPath(lastPath, depth);
        //                int currentIndex = PdfDocumentReader.GetLastSiblingIndex(parentPath) + 1;
        //                if (string.IsNullOrEmpty(parentPath))
        //                {
        //                    bookmark.Path = PdfDocumentReader.ToNodeName(currentIndex);
        //                }
        //                else
        //                {
        //                    bookmark.Path = parentPath + "." + PdfDocumentReader.ToNodeName(currentIndex);
        //                }
        //            }

        //            lastDepth = depth;
        //            lastPath = bookmark.Path;
        //            bookmarks.Add(bookmark);

        //            if(lastBookmark !=null)
        //            {
        //                lastBookmark.ToPageNumber = bookmark.FromPageNumber;
        //                lastBookmark.ToPosition = bookmark.FromPosition;
        //            }
        //            lastBookmark = bookmark;

        //            outline = pdfDoc.GetNextOutlineItem(100, false);
        //        }

        //        pdfDoc.Close();
        //    }
        //    return bookmarks;
        //}

        //private static int GetLastSiblingIndex(string path)
        //{
        //    if(path.IndexOf(".")>0)
        //    {
        //        string nodeName = path.Substring(path.LastIndexOf(".") + 1);
        //        return PdfDocumentReader.ToNodeIndex(nodeName);
        //    }
        //    else
        //    {
        //        return PdfDocumentReader.ToNodeIndex(path);
        //    }
        //}

        //private static string GetParentPath(string path)
        //{
        //    if (path.IndexOf(".") > 0)
        //    {
        //        return path.Substring(0, path.LastIndexOf("."));
        //    }
        //    else
        //        return "";
        //}

        //private static string ToNodeName(int nodeIndex)
        //{
        //    string nodeStr = nodeIndex.ToString();
        //    if (nodeIndex < 10)
        //    {
        //        nodeStr = "00" + nodeStr;
        //    }
        //    else if (nodeIndex < 100)
        //    {
        //        nodeStr = "0" + nodeStr;
        //    }
        //    return nodeStr;
        //}

        //private static int ToNodeIndex(string nodeName)
        //{
        //    return int.Parse(nodeName);
        //}

        //private static string GetParentPath(string currentPath, int parentDepth)
        //{
        //    string[] nodeNames = currentPath.Split(new char[] {'.'});
        //    string parentPath = string.Empty;
        //    for(int i=0;i<=parentDepth;i++)
        //    {
        //        parentPath += nodeNames[i];
        //        if (i < parentDepth)
        //            parentPath += ".";
        //    }
        //    return parentPath;
        //}
        //#endregion

        //#region read section 
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="fromPageNum"></param>
        ///// <param name="fromPos"></param>
        ///// <param name="toPageNum"></param>
        ///// <param name="toPos"></param>
        ///// <returns></returns>
        //public static string GetContent(string pdfFilePath, int fromPageNum, PointF fromPos, int toPageNum, PointF toPos)
        //{
        //    Single oldY = 0;
        //    System.Text.StringBuilder buffer = new StringBuilder();
        //    PDFPARSERLib.Document pdfDoc = new PDFPARSERLib.Document();
        //    if (pdfDoc.Open(pdfFilePath, ""))
        //    {
        //        PDFPARSERLib.Content content = new PDFPARSERLib.Content();
        //        PDFPARSERLib.Text text = null;
        //        int pageCount = pdfDoc.PageCount;
        //        int pageNum = fromPageNum;
        //        bool startRead = false;
        //        while (pageNum <= pageCount && pageNum <= toPageNum)
        //        {
        //            pdfDoc.PageNo = pageNum;
        //            PDFPARSERLib.Page page = pdfDoc.Page;
        //            SizeF size = new SizeF();
        //            object[] dimensions = (object[]) page.CropBox;
        //            if (dimensions != null && dimensions.Length == 4)
        //            {
        //                float pageHeight = float.Parse(dimensions[3].ToString());
        //                float pageWidth = float.Parse(dimensions[2].ToString());
        //                size = new SizeF(pageWidth, pageHeight);
        //            }

        //            PDFPARSERLib.Document pageDoc = page.Document;
        //            content = pageDoc.Page.Content;
        //            if (content == null)
        //                text = null;
        //            else
        //                text = content.GetNextText();


        //            while (text != null)
        //            {
        //                Single y = (Single) ((object[]) text.YPos)[0];
        //                y = size.Height - y;

        //                if (pageNum == toPageNum && y >= toPos.Y)
        //                    break;

        //                if (!startRead)
        //                {
        //                    if (y >= fromPos.Y)
        //                    {
        //                        startRead = true;
        //                        buffer.Append(text.UnicodeString);
        //                    }
        //                }
        //                else
        //                {
        //                    string nodeText = text.UnicodeString;
        //                    if (Math.Abs(oldY - y) > 4)
        //                        buffer.Append(Environment.NewLine + nodeText);
        //                    else
        //                        buffer.Append(" " + nodeText);
        //                }

        //                oldY = y;
        //                text = content.GetNextText();
        //            }

        //            pageNum++;
        //        }
        //    }
        //    else
        //    {
        //        pdfDoc.Close();
        //        throw new Exception("Unable to open pdf file");
        //    }
        //    return buffer.ToString();
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pdfFilePath"></param>
        ///// <param name="bookmark"></param>
        ///// <returns></returns>
        //public static string ReadBookmarkContent(string pdfFilePath, PdfBookmark bookmark)
        //{
        //    return
        //        PdfDocumentReader.GetContent(pdfFilePath, bookmark.FromPageNumber, bookmark.FromPosition,
        //                                     bookmark.ToPageNumber, bookmark.ToPosition);
        //}
        //#endregion

       
    }
}
